/*
============================================================================
 Name        : dd_http_test.c
 Author      : Jian
 Version     :
 Copyright   : GPL
 Description : dd_http_test.c - source file
============================================================================
*/

/* INCLUDE FILES */
#include "dd_http_test.h"
#include "dd_http_worker.h"
#include "dd_log.h"
#include "sd_platform.h"
#include "dd_vector.h"

#ifdef __DD_TEST

#define __TEST_TIME         50 
#define __TEST_RANDOM       1
#define __TEST_THREAD_COUNT 4

static const char* _testUrl[][2] = {
    "www.sina.com.cn", "sina",
    "www.yahoo.com", "yahoo",
    "www.hupu.com", "hupu",
    "www.sohu.com", "sohu",
    "www.baidu.com", "baidu",
    "www.163.com", "163",
    "www.weibo.com", "weibo",
    "www.zhihu.com", "zhihu",
    "www.tgbus.com", "tgbus"
} ; 

typedef struct {
    const    char* url ;
    const    char* name ;
    int      isFinished ;
    sd_file* file ;
} dd_test_http_data;

typedef struct {
    sd_rlock*  lock ;
    sd_semp*   waitSemp ;
    dd_vector* datas;
    DD_BOOL    isSucceed ;
} dd_test_http;

static dd_test_http* _testHttp = NULL ;

static void _handle_error()
{
    __DD_ASSERT_DEFENSE(_testHttp, return) ;

    _testHttp->isSucceed = DD_FALSE ;
    sd_post_sem(_testHttp->waitSemp) ;
}

static void _check_succeed() 
{
    int i = 0 ;
    
    __DD_ASSERT_DEFENSE(_testHttp, return) ;

    sd_wait_rlock(_testHttp->lock) ;

    for (; i < dd_vector_count(_testHttp->datas); i++) {
        dd_test_http_data* data = (dd_test_http_data*)dd_vector_get(_testHttp->datas, i) ;
        __DD_ASSERT_DEFENSE(data, _handle_error(); sd_post_rlock(_testHttp->lock) ; return) ;
        if (!data->isFinished) {
            sd_post_rlock(_testHttp->lock) ;
            return ;
        }
    }

    sd_post_rlock(_testHttp->lock) ;

    _testHttp->isSucceed = DD_TRUE ;
    sd_post_sem(_testHttp->waitSemp) ;
}

static int _test_start(dd_http* http) 
{
    dd_test_http_data* data = NULL ;
    char name[100] = {0} ;

    __DD_ASSERT_DEFENSE(http, _handle_error(); return -1) ;   
    
    data = (dd_test_http_data*)dd_vector_get(_testHttp->datas, (DD_UINT)http->callback.clientPtr) ;
    __DD_ASSERT_DEFENSE(data, _handle_error(); return -1) ;

    sprintf(name, "c:\\data\\player\\%s_%d.html", data->name, (int)http->callback.clientPtr) ; 

    data->file = sd_file_open((const DD_UTF8*)name, DD_FILE_REPLACE) ;
    
    __DD_ASSERT_DEFENSE(data->file, _handle_error(); return -1) ;

    return 0 ;
}
    
static int _test_process_header(const dd_http* http) 
{
    __DD_ASSERT_DEFENSE(http, _handle_error(); return -1) ;   

    return 0 ;
}

static int _test_process_body(const dd_http* http, const char* htData, int offset, int len) 
{
    dd_test_http_data* data = NULL ;

    __DD_ASSERT_DEFENSE(http && htData && len > 0 && offset >= 0, _handle_error(); return -1) ;   

    data = (dd_test_http_data*)dd_vector_get(_testHttp->datas, (DD_UINT)http->callback.clientPtr) ;
    __DD_ASSERT_DEFENSE(data, _handle_error(); return -1) ;

    sd_file_seek(data->file, offset, DD_SEEK_SET) ;
    sd_file_write(data->file, htData, len) ;

    return 0 ;
}   
    
static void _test_finish(const dd_http* http, int errorCode) 
{
    dd_test_http_data* data = NULL ;

    __DD_ASSERT_DEFENSE(http, _handle_error(); return) ;   

    data = (dd_test_http_data*)dd_vector_get(_testHttp->datas, (DD_UINT)http->callback.clientPtr) ;
   __DD_ASSERT_DEFENSE(data, _handle_error(); return) ;

    sd_file_close(data->file) ;
    
    if (errorCode < 0) {
        dd_log_error("http test got errorCode: %d when finished", errorCode) ;
        _handle_error() ;
        return ;
    }

    data->isFinished = DD_TRUE ;

    _check_succeed() ;
}

DD_BOOL dd_http_test() 
{
    dd_http_worker* worker = dd_http_worker_create(0, __TEST_THREAD_COUNT) ; 
    int i = 0 ;
    dd_http_callback callBack = {0} ;
    int ret = DD_FALSE ;

    __DD_ASSERT_DEFENSE(worker, return DD_FALSE) ;

    _testHttp = dd_malloc(sizeof(dd_test_http)) ;   
    __DD_CHECK_MEM(_testHttp, sizeof(dd_test_http), return DD_FALSE) ;
    
    _testHttp->lock = sd_create_rlock() ;
    _testHttp->waitSemp = sd_create_sem(0) ;
    _testHttp->datas = dd_vector_create(__TEST_TIME) ; 
   
    callBack.start = _test_start ;
    callBack.process_header = _test_process_header ;
    callBack.process_body = _test_process_body ;
    callBack.finish = _test_finish ;
    
    srand((DD_UINT)time(0)) ;

    for (; i < __TEST_TIME; i++) {
        
        dd_test_http_data* data = (dd_test_http_data*)dd_malloc(sizeof(dd_test_http_data)) ;
        
        int urlIndex = i ;
        if (__TEST_RANDOM) 
            urlIndex = rand() % (sizeof(_testUrl) / (2 * sizeof(const char*))) ;

        __DD_CHECK_MEM(data, sizeof(dd_test_http_data), return DD_FALSE) ;

        data->url = _testUrl[urlIndex][0] ;
        data->name = _testUrl[urlIndex][1] ;
        data->isFinished = DD_FALSE ;

        dd_vector_append(_testHttp->datas, data) ;
    }

    for (i = 0; i < dd_vector_count(_testHttp->datas); i++) {
        
        dd_http_req_get* get = (dd_http_req_get*)dd_malloc(sizeof(dd_http_req_get)) ;
        dd_test_http_data* data = (dd_test_http_data*)dd_vector_get(_testHttp->datas, i) ;

        __DD_ASSERT_DEFENSE(data, return DD_FALSE) ;
        __DD_CHECK_MEM(get, sizeof(dd_http_req_get), return DD_FALSE) ;
        
        callBack.clientPtr = (void*)i ;

        get->callback = callBack ;
        get->url = (DD_UTF8*)data->url ;
        get->port = 80 ;
        get->rangeVector = NULL ;

        __DD_ASSERT_DEFENSE(dd_http_worker_get(worker, get, 0, 0) >= 0, return -1) ;
    }

    sd_wait_sem(_testHttp->waitSemp) ;

    dd_http_worker_destroy(worker) ;
    ret = _testHttp->isSucceed ;
    // dd_free(_testHttp) ;
    return ret ;
}

#endif  /* __DD_TEST */

/* End of File */
